package com.wzcl.app.service.impl;

import com.wzcl.app.dao.model.KnowledgePoint;
import com.wzcl.app.dao.model.Topic;
import com.wzcl.app.dao.model.TopicAndKnowledgePoint;
import com.wzcl.app.dao.repository.TopicAndKnowledgePointRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.service.TopicAndKnowledgePointService;
import com.wzcl.app.service.WrongTopicService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Log4j2
@Service
@Transactional
public class TopicAndKnowledgePointServiceImpl implements TopicAndKnowledgePointService {

    @Autowired
    private TopicAndKnowledgePointRepository repository;

    @Autowired
    private WrongTopicService wrongTopicService;

    @Override
    @Caching(evict = {
            @CacheEvict(value = "TopicAndKnowledgePoint", key = "'findTopicByKnowledgePointId:'+#knowledgePoint.id"),
            @CacheEvict(value = "TopicAndKnowledgePoint", key = "'findKnowledgePointByTopicId:'+#topic.id")
    })
    public void bind(Topic topic, KnowledgePoint knowledgePoint) {
        TopicAndKnowledgePoint topicAndKnowledgePoint = getByTopicIdAndKnowledgePointId(topic.getId(), knowledgePoint.getId());
        if (topicAndKnowledgePoint == null) {
            topicAndKnowledgePoint = new TopicAndKnowledgePoint();
            topicAndKnowledgePoint.setTopic(topic);
            topicAndKnowledgePoint.setKnowledgePoint(knowledgePoint);
            repository.save(topicAndKnowledgePoint);
        }
    }

    @Override
    @Caching(evict = {
            @CacheEvict(value = "TopicAndKnowledgePoint", key = "'findTopicByKnowledgePointId:'+#knowledgePoint.id"),
            @CacheEvict(value = "TopicAndKnowledgePoint", key = "'findKnowledgePointByTopicId:'+#topic.id")
    })
    public void unBind(Topic topic, KnowledgePoint knowledgePoint) {
        //解绑关系
        TopicAndKnowledgePoint topicAndKnowledgePoint = getByTopicIdAndKnowledgePointId(topic.getId(), knowledgePoint.getId());
        if (topicAndKnowledgePoint == null) {
            throw new BusinessException(CodeMsg.TOPIC_AND_KNOWLEDGE_POINT_NOT_EXIST);
        }
        //删除关系前需要删除对应关系绑定的错题集
        wrongTopicService.delWrongTopicByTopicAndKnowledgePointId(topicAndKnowledgePoint.getId());
        //删除关系
        log.info("Topic ID:{} unBind KnowledgePoint ID:{} -->TopicAndKnowledgePoint Physical deletion", topic.getId(), knowledgePoint.getId());
        repository.delete(topicAndKnowledgePoint);
    }

    //通过题目删除关系
    @Override
    @CacheEvict(value = "TopicAndKnowledgePoint", allEntries = true)
    public void unBind(Topic topic) {
        //删除之前接触错题记录中的数据
        wrongTopicService.delWrongTopicByTopicId(topic.getId());
        //删除
        log.info("TopicAndKnowledgePoint Physical deletion By Topic Id {}", topic.getId());
        repository.deleteByTopicId(topic.getId());
    }


    //通过知识点删除关系
    @Override
    @CacheEvict(value = "TopicAndKnowledgePoint", allEntries = true)
    public void unBind(KnowledgePoint knowledgePoint) {
        //删除之前接触错题记录中的数据
        wrongTopicService.delWrongTopicByKnowledgePointId(knowledgePoint.getId());
        //删除
        log.info("TopicAndKnowledgePoint Physical deletion By KnowledgePoint Id {}", knowledgePoint.getId());
        repository.deleteByKnowledgePointId(knowledgePoint.getId());
    }

    @Override
    @Cacheable(value = "TopicAndKnowledgePoint", key = "#root.methodName+':'+#knowledgePointId")
    public List<Topic> findTopicByKnowledgePointId(Integer knowledgePointId) {
        List<TopicAndKnowledgePoint> list = repository.findAllByKnowledgePointId(knowledgePointId);
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return list.stream().map(TopicAndKnowledgePoint::getTopic).collect(Collectors.toList());
    }


    @Override
    @Cacheable(value = "TopicAndKnowledgePoint", key = "#root.methodName+':'+#knowledgePoint.id")
    public List<Topic> findTopicByKnowledgePointId(KnowledgePoint knowledgePoint) {
        return findTopicByKnowledgePointId(knowledgePoint.getId());
    }

    @Override
    @Cacheable(value = "TopicAndKnowledgePoint", key = "#root.methodName+':'+#topicId")
    public List<KnowledgePoint> findKnowledgePointByTopicId(Integer topicId) {
        List<TopicAndKnowledgePoint> list = repository.findAllByTopicId(topicId);
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return list.stream().map(TopicAndKnowledgePoint::getKnowledgePoint).collect(Collectors.toList());
    }

    @Override
    @Cacheable(value = "TopicAndKnowledgePoint", key = "#root.methodName+':'+#topic.id")
    public List<KnowledgePoint> findKnowledgePointByTopicId(Topic topic) {
        return findKnowledgePointByTopicId(topic.getId());
    }

    @Override
    public List<TopicAndKnowledgePoint> findTopicAndKnowledgePointByTopic(Topic topic) {
        List<TopicAndKnowledgePoint> list = repository.findAllByTopicId(topic.getId());
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return list;
    }


    private TopicAndKnowledgePoint getByTopicIdAndKnowledgePointId(Integer topicId, Integer KnowledgePointId) {
        return repository.findByTopicIdAndKnowledgePointId(topicId, KnowledgePointId);
    }
}
